package com.yonyou.pmclouds.ncinvoker.invoker;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yonyou.pmclouds.basecom.runtime.RuntimeEnvironment;
import com.yonyou.pmclouds.im.util.IMHttpTookit;
import com.yonyou.pmclouds.ncinvoker.conf.NCInvokerProperties;
import com.yonyou.pmclouds.ncinvoker.entity.NCInvokerResult;
import com.yonyou.pmclouds.ncinvoker.entity.NCServiceVO;
import com.yonyou.pmclouds.ncinvoker.itf.NCInvoker;
import com.yonyou.pmclouds.ncinvoker.itf.NCInvokerCallBack;
import com.yonyou.pmclouds.ncinvoker.thread.NCInvokerTask;
import com.yonyou.pmclouds.ncinvoker.thread.NCThreadPool;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.util.Map;
import java.util.concurrent.*;

@Slf4j
public class NCDirectInvoker implements NCInvoker {

    public static final String NC_SERVICE_SERVLET_PATH = "/service/PMCloudDriveProjectStateServlet";

    private static ObjectMapper mapper = new ObjectMapper();

    static {
        mapper.configure(JsonParser.Feature.ALLOW_MISSING_VALUES, true);
    }


    private NCInvokerProperties properties;
    private String ncServiceUrl;

    public NCDirectInvoker(NCInvokerProperties properties) {
        this.properties = properties;
        //this.ncServiceUrl = properties.ncAddress + NC_SERVICE_SERVLET_PATH;
    }

    @Override
    public NCInvokerResult invokeSync(NCServiceVO serviceVO, Map<String, Object> params, String tenant, String user) {
        //  集团及帐套
        params.put(DATA_SOURCE_CONST, properties.getNcDataSource());
        params.put(GROUP_CONST, properties.getNcGroupId());
        params.put(SERVICE_NAME_CONST, serviceVO.getServiceName());
        String result = null;
        ncServiceUrl = this.properties.getNcAddress() + serviceVO.getServicePath();
        log.info("nc直连调用url:{}，参数params:{}", ncServiceUrl, params);
        try {
            result = IMHttpTookit.doPostWithJson(ncServiceUrl, mapper.writeValueAsString(params), null);
        } catch (JsonProcessingException e) {
            log.error("nc invoke failed: serialization failed");
            return new NCInvokerResult(NCInvokerResult.STATUS_INTERNAL_ERROR, null, null);
        } catch (Exception e) {
            return new NCInvokerResult(NCInvokerResult.STATUS_FAILED, e.getMessage(), null);
        }
        if (result == null) {
            return new NCInvokerResult(NCInvokerResult.STATUS_OK, null, null);
        }
        String t = result;
        try {
            t = mapper.readValue(result, String.class);
        } catch (IOException e) {
            log.error("", e);
        }
        if (result.contains("responseCode")) {
            return new NCInvokerResult(NCInvokerResult.STATUS_FAILED, t, null);
        }
        return new NCInvokerResult(NCInvokerResult.STATUS_OK, t, null);
    }

    @Override
    public Future<NCInvokerResult> invokeAsync(NCServiceVO serviceVO, Map<String, Object> params, String tenant, String user, final NCInvokerCallBack callBack) {
        // TODO 整个线程池？有点不太想搞线程池了，已经有两个了。。。
        return NCThreadPool.getInstance().getExecutor().submit(new NCInvokerTask(serviceVO,params, tenant, user) {

            @Override
            public NCInvokerResult call() throws Exception {
                NCInvokerResult result = NCDirectInvoker.this.invokeSync(serviceVO, this.getParams(), this.getTenant(), this.getUser());
                try {
                    if (callBack != null) {
                        RuntimeEnvironment.setLoginUserId(this.getUser());
                        RuntimeEnvironment.setTenantId(this.getTenant());
                        callBack.whenResult(result);
                    }
                } catch (Exception e) {
                    log.error("invoke nc service {} callback failed in tenant {}, error is {}", serviceVO.getServiceName(), this.getTenant(), e);
                }
                return result;
            }
        });
    }
}
